#include "be_tcp_socket.h"

BeTcpSocket::BeTcpSocket() : m_socket(0), m_socketSet(0)
{

}

BeTcpSocket::BeTcpSocket( TCPsocket socket ) : m_socket(socket), m_socketSet(0)
{
	m_socketSet = SDLNet_AllocSocketSet(1);
	SDLNet_TCP_AddSocket( m_socketSet , m_socket );
}


void BeTcpSocket::open( const char* const hostIp, const Uint16 port )
{
	IPaddress ip;
	// 	Resolve the host we are connecting to
	if ( SDLNet_ResolveHost(&ip, hostIp, port) == -1 )
	{
		fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
		exit(EXIT_FAILURE);
	}
	open(ip);
}

void BeTcpSocket::open( IPaddress& ipAddress )
{
	if(m_socket==0)
	{
		// 	 Open a connection with the IP provided (listen on the host's port) 
		if ( !(m_socket = SDLNet_TCP_Open(&ipAddress)) )
		{
			fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
			exit(EXIT_FAILURE);
		}
		m_socketSet = SDLNet_AllocSocketSet(1);
		SDLNet_TCP_AddSocket( m_socketSet , m_socket );
	}
}

void BeTcpSocket::close()
{
	if(m_socketSet)
	{
		SDLNet_TCP_DelSocket( m_socketSet , m_socket );
		SDLNet_FreeSocketSet(m_socketSet);
		m_socketSet=0;
	}
	if(m_socket)
	{
		SDLNet_TCP_Close( m_socket );
		m_socket=0;
	}
}

size_t BeTcpSocket::send( const void* const data, const size_t size )
{
	if(m_socket)
	{
		const int sizeWritten=SDLNet_TCP_Send(m_socket, data, size);
		if ( sizeWritten < size)
		{
			fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
			close();
			return 0;
		}
		return sizeWritten;
	}
	return 0;
}

size_t BeTcpSocket::recieve( void* const data, const size_t size )
{
	if(m_socket)
	{
		const int sizeRead=SDLNet_TCP_Recv( m_socket, data, size);
		if ( sizeRead < 0 )
		{
			fprintf(stderr, "SDLNet_TCP_Recv: %s\n", SDLNet_GetError());
			close();
			return sizeRead;
		}
		return sizeRead;
	}
	return 0;
}

bool BeTcpSocket::isReady()
{
	if(m_socket&&m_socketSet)
	{
		if(SDLNet_CheckSockets(m_socketSet, 0))
		{
			return SDLNet_SocketReady(m_socket)!=0;
		}
	}
	return false;
}

boost::shared_ptr<BeTcpSocket> BeTcpSocket::accept()
{
	if(m_socket)
	{
		if( TCPsocket socket = SDLNet_TCP_Accept(m_socket) )
		{
			return boost::shared_ptr<BeTcpSocket>(new BeTcpSocket(socket));
		}
	}
	return boost::shared_ptr<BeTcpSocket>();
}
